Repository navigation
The add-on partitioned once, custom multigrid on empty ranks, and the rotated solve's switch and record - #890
Merged
Merged
Conversation
…a datum-only solve ThinSheet.normal_velocity sets the datum of the sheet-tangency constraint, so a sheet on a manifold can move along its normal (the radial motion of a tidally flexed shell over an ocean) and its in-plane strain rate carries the curvature term through the nodal normals. In the rotated nonlinear loop a cold start whose only forcing is the prescribed datum had a zero residual at u = 0 and returned converged in zero iterations before the lift was applied; the convergence test now waits for the lift and takes its reference scale from the lifted iterate. tests/test_1092: breathing (u = W rhat exactly, stress 6 eta W P) and the degree-2 membrane closed form (tangential velocity 3/11 of the radial pattern's surface gradient; 7.2, 3.4, 2.5 percent at h 0.3, 0.2, 0.15). scripts/sessions/tidal_shell/tidal_shell.py: the eccentricity-tide driver (degree 2, viscous or Maxwell sheet, collective diagnostics against the closed form, Mollweide maps). Underworld development team with AI support from Claude Code
… sphere, in-plane principal stresses The maps were drawn from a rank-local evaluation of the whole grid (garbage outside rank 0's cells) and the largest principal stress picked up the zero normal eigenvalue where both in-plane stresses were compressive. Underworld development team with AI support from Claude Code
… datum on fault pairs When rigid rotations are a genuine null space (a drag-free sheet on a sphere, a free-slip shell) the inner solve cannot reduce the residual's component along them, so the outer nonlinear residual is now measured in that quotient space, as it already was for the pressure gauge. A viscoelastic stress history on the faceted surface leaves such a component (measured: a tidally flexed Maxwell sheet floored at a relative residual of 1e-4 with every linear solve converged; one iteration per step after the change). The projected-out magnitude is kept on the solver as _rotated_rotation_gauge_residual. A split-fault pair on a manifold takes its tangency through the pair block, so a prescribed sheet normal velocity now rides the pair's mean-normal row (sqrt2 w, signed against the analytic normal); before, the fault nodes stood still while the sheet breathed (datum error 0.018 against an amplitude of 0.1). Tidal driver: tiger-stripe faults (count, length, spacing, latitude, interface law), per-step stress diagnostics on a collective grid through nodal stress components (the stress expression's velocity gradients cannot cross ranks), the objective-rate option, and the sweep plot script. Underworld development team with AI support from Claude Code
…, shear invariant, speed) and the faulted-versus-unfaulted comparison script Underworld development team with AI support from Claude Code
…re stress against a reference run Underworld development team with AI support from Claude Code
…circle optimum) beside the stripe-parallel receivers Underworld development team with AI support from Claude Code
…rden, driving-traction probes on virtual stripes, stripe azimuth, cycle plots and the Berne et al. figure analogue CoulombFaultLaw takes a constant effective normal stress added to the reaction-fed one (compression positive), the clamped-but-modulated fault of Berne et al. 2024. Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
…ckness to the sheet's resultant units; clamping reported as a stress Underworld development team with AI support from Claude Code
…et topology On a sheet on a sphere the fault is an edge carried by a 3-vector; the de-smearing mass picked the triangle's weights by the component count and gave the mid-edge nodes an eighth of their mass, so the effective normal stress the interface laws read (and the friction they produced) was off by node-dependent factors of 5 to 8. The reaction is the membrane resultant, L sigma_nn, now to 0.4 percent on every pair of the breathing sphere (test_1092). Underworld development team with AI support from Claude Code
…he prediction in the sweep plot Amplitude (24/11) mu A wt/sqrt(1+wt^2) and lag atan(1/wt): measured at 128 steps per period 0.0195 against 0.0193 and 32 against 28 degrees at De 0.3; the lag excess is first order in the step (15 degrees at 32 steps per period). Underworld development team with AI support from Claude Code
…tion coefficient Underworld development team with AI support from Claude Code
… saved per step for the site analysis Underworld development team with AI support from Claude Code
…pe-plane tractions (phase of the clamping, Coulomb asymmetry index); the overlay takes labelled runs Underworld development team with AI support from Claude Code
… azimuth Underworld development team with AI support from Claude Code
…ycle, the excess and the slip it drives Underworld development team with AI support from Claude Code
…and polar grids, saved at cycle boundaries Underworld development team with AI support from Claude Code
…ulted Underworld development team with AI support from Claude Code
…rules A fault placed as a ladder on a copy of the base's finest level gets only the welded tail (A); in a yielding, convecting box its velocity sub-solve caps at 200 once the lid mobilises. Building C by hand, the same ladder at 4S and 2S on the coarser base levels, each split along its own rungs, keeps the Newton-phase velocity iterations at 29-38 with no caps (A: 71-200, 2 caps) at A's cost per cycle. New capability guide guides/faults-in-convection.md (skill link included): the lean tail, the rotated loop's warm-start rules (first solve from rest; newton_switch_rtol measured from each solve's own residual, so warm solves need it at 1), rebuilding for a moving trench (shifted warm start, Picard first, rebuild every few rungs), and the measured traps. The design note records the A / C comparison and lists the ribbon replay as not yet done. Underworld development team with AI support from Claude Code Claude-Session: https://claude.ai/code/session_019aromUkeWWPzcL2Kb8365E
…le-integrated activity and net offset), saved at orbit boundaries Underworld development team with AI support from Claude Code
… profiles (Berne et al. Fig. 4 style) Underworld development team with AI support from Claude Code
… kinked chain of arcs lost part of its cut silently) Underworld development team with AI support from Claude Code
…polar view Underworld development team with AI support from Claude Code
…pe block Underworld development team with AI support from Claude Code
…noise floor (the unfaulted shell's residual) Underworld development team with AI support from Claude Code
…before the cycle's first step (it missed one step) Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
Three fixes found by the tumbling-fault Mohr sweep, brought onto this branch for the box fault study: - fault_contact: the 3-D fault normal traction is recovered pointwise (a linear fit of the P2-triangle consistent load on the facet vertices) rather than by dividing by P1 sub-lumped masses, which read zero at every vertex and 4/3 of the value at every midpoint. The branch is keyed on the facet topology (mesh.dim), not the coordinate dimension, so the edge fault on a surface mesh keeps its lumped path. - place_surface: the sheet cavity is closed in the three shapes that defeated it on adapted meshes (an enclosed kept cell, a pinched shell vertex, a flat fill tet), with a bounded refill loop. - fault_split: a single split_fault keeps the mesh's multigrid tail, as the network path already did. Tests: the pointwise 3-D traction and the multigrid-tail checks in test_0848; the adapted-mesh placement cases as test_0867 (0864 was taken on this branch). Underworld development team with AI support from Claude Code
…s glued by name Two blocking findings. A cut, placed or split child of a partitioned host could not be partitioned again (the fault-network route places one sheet at a time), because the first add-on level's parent on the base was searched locally on a pair the first partition had moved apart; it is now read from the recorded provenance. And a split fault's facets are single-sided, so a support-based interior test never glued it and a second partition could peel its star across a seam; the faults a mesh carries are now glued by name (every pairing and its sides, every placed sheet), which also stops a domain-spanning internal boundary from being glued. The provenance is recorded when the surgery makes a mesh (inherit_provenance in the cut, the placement and the split), so it survives a later move of the nodes and the transfer needs no location. The provenance pair keeps the finest level's FAC patch. Empty region ids no longer reach the balance; a level that would sit on one rank is refused; the inside tolerances agree; the polyline reach is reconciled over the seam; the balance cannot overshoot by a unit; the remaining non-collective raises are collective; the 3-D sheet fault on a refined base takes its coarse levels in serial as in parallel. Tests: a second partition keeps the first fault whole (2-D, np 2/4/8); two sheets placed in turn and split together (3-D); the placement test compares facets and pairs with its own serial run and the tail by identity; fixtures shared in tests/parallel/fault_fixtures.py. Docs: the design note's unit and retirement statements corrected, supersession notes in the September placement note, FAULT_MULTIGRID_HIERARCHIES and the conforming-surfaces page; review record in docs/reviews/2026-10. Underworld development team with AI support from Claude Code
…tes partitioned utilities/_plex_topology.pyx builds, in one C loop per stratum, the tables the fault, placement and add-on code assembled one petsc4py call at a time: closures by depth, supports, a per-cell section and its offsets, each cell's dof rows. The partition, the region growth shared with the placement gather, the marking rules, the redistribution's per-cell fields, the edge and cell-size tables, the mesh's point-location index and per-cell node table are now array operations on them, and the node-cloud transfer builders assemble once instead of a row per call. Every converted function is identical to its previous version, entry for entry, serially and on four ranks. The 3-D partition at 87,525 cells on four ranks went from 6.87 s to 1.35 s, the 2-D one at 94,910 from 2.94 s to 0.64 s. The point-location index takes each cell's vertex count from the closure: the element table gives 4 for a 1-D surface mesh's line cell, and the old slice of the closure took the edge point itself as a vertex there. The same count in three other mesh functions is flagged TODO(BUG). FaultNetwork.build (3-D band) and place_fault_ribbon_2d in gather mode partition before placing (mark_band, a superset of the placement's mask), so the placement moves nothing and adopt_hierarchy keeps the base's own levels under the partitioned host instead of co-locating copies. A direct place_sheet call gathers with two growth layers; with one it refused on a partitioned adapt child. A pre-existing mismatch is flagged TODO(BUG): the native checkpoint payload is written under /restart/petsc while the split-mesh reader looks at the top level, so test_0864's two-sided round trip fails here and on feature/tidal-shell. Tests: test_1098 (tables against DMPlex, serial and 3 ranks), test_1099 (band route, 2 and 4 ranks), test_1097 direct placement (shown failing first). Quick tier A: 1484 passed, 1 failed (the flagged checkpoint test); parallel batch at 2 ranks all passed. Underworld development team with AI support from Claude Code
The table that says how many faces and vertices a cell has had no 1-D entry, so a 1-D surface mesh (an annulus boundary, extract_surface) fell through to the tetrahedron entry and read 4 faces and 4 vertices per line cell. The face control-point builders, the geometry audit and the visualisation slice cell closures by those counts, and a line's closure has 3 points, so the slice took the line itself as a vertex. A line cell now has two faces, its two vertices, and the three TODO(BUG) markers left by the previous commit are resolved at the source rather than per function. Point location on a 1-manifold now evaluates exactly: the annulus case of test_0772's surface evaluate, an expected failure that blamed exactly this, passes serially and on 2 and 3 ranks, and is no longer marked. Test: tests/test_1100_element_table_matches_closures.py (the table against every cell's cone and closure on a 1-D surface, triangles, quadrilaterals, tetrahedra and a 2-D surface in 3-D), shown failing on the line case first. Every serial and parallel test building a 1-D or manifold mesh passes. Underworld development team with AI support from Claude Code
A coarse level is small, and a placed fault mesh is gathered onto its surgery rank, so on a large run most ranks own no cell of the coarsest level and many own no fine cell either. Found on kaiju at np 104 with a 124-cell coarsest level (the faulted annulus): ranks without cells raised, the others waited in the next all-gather. Four places assumed a rank holds something: - _colocate_level shaped its centroid arrays from the cells it found. An empty rank gave shape (0,), so np.zeros((0, shape[1])) raised IndexError and the vstack of the all-gathered centroids failed on every rank. Both arrays are now (-1, cdim) from the DM's coordinate dimension. - build() took each level's component count as local DOFs over local nodes: ZeroDivisionError on a rank with no node. It is the field's count, now taken over the whole level. - _node_transfer_no_repair triangulated the rank's local coarse cloud: "No points given" on an empty rank. A rank with no fine node returns no rows; one with too few coarse nodes to span a simplex counts its fine nodes as outside the local hull, which already sends the "auto" build across partitions. - _fac_patch_split_parallel indexed the coarse selection with a clipped index on rows that have no coarse node: IndexError on a rank with fine rows and no coarse nodes (seen at np 16). tests/parallel/test_1103 (written first): colocating a 4-cell coarsest level with empty ranks, and a custom-P FMG Poisson solve on a 4-cell coarsest level against GAMG. Before: IndexError / ZeroDivisionError on 7 of 8 ranks and a hang on the eighth; after the first three fixes, IndexError at np 16. Now 2 passed at np 4, 5, 8, 16 and 32. The parallel custom-MG tests (1017, 1064, 1095, 1096, 1097, 1099): 22 passed, 3 skipped at np 2 and 4. tests/parallel/test_*.py runs it in CI. Underworld development team with AI support from Claude Code
Two more places that assumed every rank holds part of a level, both on the first faulted-mesh build: - line_cut._edge_vertices built its (n_edges, 2) table from the edges it found; a rank with none got shape (0,), and _crossing_parameters' ends[:, 0] raised IndexError there while the other ranks waited. It is now reshape(-1, 2). - fault_mg.provenance_transfer_parallel packed its star-forest roots with reshape(nc_loc, -1); with no coarse cell, reshape(0, -1) cannot infer the width and raised ValueError. The widths are now explicit. The raise was caught by build_transfers' per-rank retry, so the failing ranks started an RBF rebuild alone and the job died in mismatched collectives (MPI_ERR_BUFFER, "Message truncated") -- the kaiju np 32 / 52 signature. Measured on a faulted annulus at np 32 (cell 0.35, four refinements) and np 8 (cell 0.8): the three or two ranks with no coarse cell raised here. tests/parallel/test_1103 gains a line cut on a mesh where most ranks hold no cell (written first: IndexError on 7 of 8 ranks and a hang on the eighth; now 3 passed at np 8). The provenance fix has no CI-sized test yet: the faulted annulus at np 8 still diverges later, inside the rotated solve, and is kept out of the suite until that is understood. Provenance-path tests (1096, 1097, 1099) at np 2: 9 passed. Underworld development team with AI support from Claude Code
…eference The rotated nonlinear loop tests convergence against ref = max(r0, ||F(0)||), the rest-state residual (the warm-start rtol cure), but its Picard->Newton continuation switch still read rnorm <= switch_rtol * r0, the warm start's own residual. A warm start is already in Newton's basin, yet had to shrink its residual a hundredfold under Picard first: on the fault campaign, rebuild steps took 23-27 nonlinear iterations against 4 for ordinary steps. The switch now reads ref, and the result dict records the iteration it fired at (continuation_switch_iteration). Measured on test_1018's power-law box, re-solved from a converged state after a 1% change in the body force: switch at iteration 12, 13 iterations in all, before; switch at iteration 0, 2 iterations, after. The cold solve is unchanged (switch at 15, 17 iterations): there ref is r0. The generic path was already consistent: its continuation ramp keys alpha and the stop on F_ref = max(||F(0)||, F_start). No other solver loop compares a threshold with r0. test_rotated_continuation_warm_start_switches_to_newton_at_once (written first; with only the record added it failed "assert 12 in (0, 1)"). Rotated suite (test_1018 x2, 0062, 1066, 1021, 1058, 0203, 0019, 0020, 0013, 1070, 1073): 133 passed. Underworld development team with AI support from Claude Code
… reference A campaign that wants to record how its nonlinear solves behave (the zg95 annulus rollback runs, where fault rebuilds are the point of the experiment) had to scrape -uw_verbose logs for numbers the loop already computes. The result dict now carries them: - "fnorm_rest": the rest-state residual ||F^(0)|| (warm starts; None cold) - "ref": max(r0, fnorm_rest), what the convergence and Picard->Newton switch tests compare against - "rnorm_history": ||F^|| at every iteration start (its or its+1 entries; the last equals "rnorm") - "line_search_alpha": the step accepted for each increment, one per increment (1.0 full step or the lift; a halved alpha on a cutback; 0.0 when the increment was not applied: a line-search stall or the step-norm exit) _backtracking_line_search returns (u, improved, alpha); its only caller is the rotated loop. No extra residual evaluations or solves. test_rotated_solve_records_its_diagnostics (written first; on 371d3bd it failed with KeyError 'rnorm_history'): cold and warm re-solves of the power-law box, checking the lengths, the history's ends against rnorm0 and rnorm, fnorm_rest None cold and > 0 warm, ref = max(rnorm0, fnorm_rest), and a full final step at the solution. test_1018: 27 passed (kaiju, 1 rank, overlay on 371d3bd). Written on kaiju (local commit 16ae9d2b) and relayed through the hub, since kaiju holds no GitHub credentials. Underworld development team with AI support from Claude Code
…eference The rotated nonlinear loop tests convergence against ref = max(r0, ||F(0)||), the rest-state residual (the warm-start rtol cure), but its Picard->Newton continuation switch still read rnorm <= switch_rtol * r0, the warm start's own residual. A warm start is already in Newton's basin, yet had to shrink its residual a hundredfold under Picard first: on the fault campaign, rebuild steps took 23-27 nonlinear iterations against 4 for ordinary steps. The switch now reads ref, and the result dict records the iteration it fired at (continuation_switch_iteration). Measured on test_1018's power-law box, re-solved from a converged state after a 1% change in the body force: switch at iteration 12, 13 iterations in all, before; switch at iteration 0, 2 iterations, after. The cold solve is unchanged (switch at 15, 17 iterations): there ref is r0. The generic path was already consistent: its continuation ramp keys alpha and the stop on F_ref = max(||F(0)||, F_start). No other solver loop compares a threshold with r0. test_rotated_continuation_warm_start_switches_to_newton_at_once (written first; with only the record added it failed "assert 12 in (0, 1)"). Rotated suite (test_1018 x2, 0062, 1066, 1021, 1058, 0203, 0019, 0020, 0013, 1070, 1073): 133 passed. Underworld development team with AI support from Claude Code
… reference A campaign that wants to record how its nonlinear solves behave (the zg95 annulus rollback runs, where fault rebuilds are the point of the experiment) had to scrape -uw_verbose logs for numbers the loop already computes. The result dict now carries them: - "fnorm_rest": the rest-state residual ||F^(0)|| (warm starts; None cold) - "ref": max(r0, fnorm_rest), what the convergence and Picard->Newton switch tests compare against - "rnorm_history": ||F^|| at every iteration start (its or its+1 entries; the last equals "rnorm") - "line_search_alpha": the step accepted for each increment, one per increment (1.0 full step or the lift; a halved alpha on a cutback; 0.0 when the increment was not applied: a line-search stall or the step-norm exit) _backtracking_line_search returns (u, improved, alpha); its only caller is the rotated loop. No extra residual evaluations or solves. test_rotated_solve_records_its_diagnostics (written first; on 371d3bd it failed with KeyError 'rnorm_history'): cold and warm re-solves of the power-law box, checking the lengths, the history's ends against rnorm0 and rnorm, fnorm_rest None cold and > 0 warm, ref = max(rnorm0, fnorm_rest), and a full final step at the solution. test_1018: 27 passed (kaiju, 1 rank, overlay on 371d3bd). Written on kaiju (local commit 16ae9d2b) and relayed through the hub, since kaiju holds no GitHub credentials. Underworld development team with AI support from Claude Code
# Conflicts: # src/underworld3/utilities/rotated_bc.py # tests/test_1018_rotated_freeslip.py
…' into HEAD # Conflicts: # src/underworld3/utilities/rotated_bc.py
… the review fixes) Six conflicts, resolved: - constitutive_models.py (two hunks) and ddt.py (two): development's _etd_maxwell_time / _update_exp_values (#851: the step as its own constant, the declared vanishing floor, expm1, units) supersede this lineage's 9e97670, which made the same repair (a viscosity varying in space keeps its elastic response); test_1093 from 9e97670 stays and checks it. - solvers.py: development's #850 guard in _check_velocity_preconditioner, with this lineage's fault-contact marker kept (a faulted solve with no walls takes the same rotated loop). - thin_sheet.py: the lineage's normal_velocity property, then the review's add_basal_drag(conds, ...). - scripts/test.sh: the review's comment on the test_108*/test_109* batch. - fault-split-multigrid.md: the lineage's text (it removed co-location: the add-on is partitioned once), not the review's co-location bullet. Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code
Underworld development team with AI support from Claude Code # Conflicts: # scripts/sessions/fault_mg/fig_parallel_load.py
…gauge vectors - guides/faults-in-convection.md (a capability guide, read as a skill) said solve(picard=N) raises on the rotated path and that the Newton switch reads the warm start's own residual, with newton_switch_rtol = 1.0 as the workaround; on this branch picard=N stages Picard then Newton and the switch reads the convergence reference (371d3bd). Corrected. - Campaign drivers and probes leave the repository (Louis, 2026-10-28): scripts/sessions/parallel_addon, tidal_shell, box_fault_cyclic, and the last fault_mg file; the design note's probe references say where they live. - test_1093 duplicated development's test_1053 (same fixture and checks) and is removed. New tests start at tier B: test_1098, test_1100's table test, and the two newest tests of test_1018, whose tiers now go on each test. - The rotated solve destroys its rotation-gauge mode vectors (one leaked per mode per solve) and warns when the projected-out rigid-rotation component dominates a converged residual, as the pressure gauge does (a net torque on free-slip walls has no solution and reported converged in silence). - FAULT_MULTIGRID_HIERARCHIES no longer lists co-location as to come. Underworld development team with AI support from Claude Code
Member
Author
Adversarial reviewThe parallel-addon lineage had its own review on 2026-10-17 ( Fixed
Merge resolutions (c842c11)
Left open (filed)
Attacks that failed
Merge conditions
|
🔍 Architectural Review ChecklistThank you for submitting an architectural review! Reviewers should validate: Design & Architecture
Implementation
Testing & Validation
Documentation
Review Process: See CODE-REVIEW-PROCESS.md Approval: This PR merge = Review formally approved |
|
✅ Test Suite: success |
…base level The prose placed the 2S and 4S ladders one and two levels below the finest. The guide's own code (host = base_levels[len - k] for k = chain..1) and its cell counts (lean chain 642, 2924, 10950, 11612) put 2S on the finest base level beside the S ladder and 4S one level down; the coarser levels stay welded. Underworld development team with AI support from Claude Code
|
✅ Test Suite: success |
This was referenced Oct 29, 2026
custom_mg: an unsplit placed-ribbon coarse tail exhausts node memory before the first iteration
#893
Open
lmoresi
changed the base branch from
feature/fault-split-multigrid
to
development
October 29, 2026 20:19
lmoresi
added a commit
that referenced
this pull request
Oct 29, 2026
Development now carries #863's sharded CI, and #882, #889 and #890 (this branch's base). The one conflict was scripts/test.sh: test_1090's serial entry now takes the batch form, on shard 4 beside test_1069. All 382 test files are reachable (check_test_coverage). Underworld development team with AI support from Claude Code
This was referenced Oct 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The rest of the fault-split work, stacked on #889 (split-level fault multigrid); retarget to
developmentwhen that merges. Together with #882 (the rebuild leak) this is everything UWTN 2026-018 and 2026-022 describe.What it adds
utilities/addon_partition.py,docs/developer/design/parallel-addon-distribution-2026-10.md): the finest mesh built on a static base byadapt, a cut, a placement or a split is partitioned for load once, with its add-on levels, and every transfer to it is partition-agnostic (recorded provenance, not location). A second partition keeps a split fault whole; faults are glued by name. Reviewed 2026-10-17 (record indocs/reviews/2026-10/).ThinSheet.normal_velocity): the breathing of a tidally flexed shell._plex_topology.pyx).Measured
UWTN 2026-022's fixture on this head: split 5 / welded 13 velocity iterations at k = 3, peak slip 0.1589860839 / 0.1589859512 (the note's figures); the note's "Using it" recipe runs as written. On the head before today's merges, the note's README numbers reproduced at np 1 (all of them) and np 4 (same hierarchies; iterations within one; slip within 2.4e-6).
Review
The parallel-addon lineage was reviewed on 2026-10-17. Today a pass on the whole of this PR's delta (the merged rotated solve, today's merges, the add-on and empty-rank code, the tests) found two must-fix items and several should-fix ones; the first comment lists them and what was done.
Suites (laptop, macOS, this head): tier A level 1 serial 1498 passed, 44 skipped, 0 failed;
tests/parallelat np 2 180 passed, 15 skipped, 1 failed; at np 4 191 passed, 4 skipped, 1 failed; no hangs. The one failure istest_1063_constrained_freeslip_parallel[ti](#826), as on development. Until #882 merges this PR's diff includes it; it drops out when #882 lands on development and #889 takes development in.Issues
Left open by this PR, found in its review: #883 (the cold-start datum lift's convergence reference), #884 (the rotation-gauge projection measured from the second assembly), #885 (
custom_mg.last_builder_statsis module-global; curved boundaries trigger the cross-partition rebuild), #886 (a rank-local exception decidesbuild_transfers' retry), #887 (docs and messages behind the code), #888 (test reach: the cross-partition builder, an np 2 empty-rank case, test_1094's clamp).Underworld development team with AI support from Claude Code